package net;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class TcpEchoServer {
    private ServerSocket socket = null;

    public TcpEchoServer(int port) throws IOException {
        socket = new ServerSocket(port);//在构造服务器的时候给服务器固定一个端口号
    }

    //弄个线程池来处理processConnect
    private ExecutorService executorService = Executors.newCachedThreadPool();

    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            //对于TCP协议来说,与udp不同之一为tcp是连接的, 所以我们在接受情求之前需要先与客户端建立连接
            //1.建立连接
            //对于此处的socket而言,每一个客户端都会accept一次,都会新创建出来一个新的Socket交给clientSocket引用, 那么之前的clientSocket我们就得去关闭了

            Socket clientSocket = socket.accept();//Socket被理解成第二个网卡, 通过这个网卡来接受请求 发送请求
            //2.处理连接
//            Thread t = new Thread(() -> {
//                try {
//                    processConnect(clientSocket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            t.start();
            executorService.submit(() -> {
                try {
                    processConnect(clientSocket);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            //连接关闭循环去接受其他连接
        }
    }

    private void processConnect(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端连接\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());
        //这里是通过Socket内置的流对象来实现输入输出
        try (InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream()) {
            while (true) {
                Scanner scanner = new Scanner(clientSocket.getInputStream());
                PrintWriter printWriter = new PrintWriter(clientSocket.getOutputStream());
                //如果不flush 就会在这阻塞
                //如果使用print发来的request中没有\n这种空白符 就会导致hasNext方法阻塞
                if (!scanner.hasNext()) {
                    //连接断开
                    break;
                }
                //1.从inputstream内读取请求
                String request = scanner.next();//读到的字节流自动转换成字符串,比read更加方便
                //2.针对请求进行计算
                String response = process(request);
                System.out.println("即将返回的响应内容: " + response);
                //3.构建响应
                printWriter.println(response);
                printWriter.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //关闭连接
            clientSocket.close();
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9090);
        server.start();
    }

}
